/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			cc_l2d.h
  \date			june 2010
  \author		TNick

  \brief		Contains the definition of CC_L2D class and related


  Copyright (c) 2011, Nicu Tofan
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
 * Neither the name of the copyright holder nor the
   names of its contributors may be used to endorse or promote products
   derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL NICU TOFAN BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */


/*!


*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef		__CC_L2D_INC__
#define		__CC_L2D_INC__
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

class	CC_L2D;
class	CC_HDL2D;

#include	<QtGlobal>
#include	<QDebug>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/// class representing the list header in a linked list system
/**
*	\section overv			Overview
*	These lists are simple chains of objects. Each list must have:
*	- a header (CC_HDL2D) that holds a pointer to the first item
*	- a number of 0 or more items that inherit from CC_L2D (holding only a
*	forward and a backward pointer).
*
*
*	\section new_del		Creation and destruction
*	The constructor for this class only initialises itself. No chain can be
*	appended at the moment of creation. Destruction code makes use of the
*	erase() function to destroy all child elements (it assumes that the
*	elements were allocated using new() and deletes them using delete).
*
*	The erase() function is public and may be used at any time to clean the
*	list and delete all items in it (freeing of memory included). Also,
*	low level access to internal fields is allowed using setFirst() and
*	setCount();
*
*
*	\section retrieve_item	Retrieveing an item
*	To get an item at a particular o based index use item(). Firsta nad last
*	items in the chain may be found using first() and last().
*
*
*	\section informative	Informative functions
*	To get the number of items that are hosted inside a chain use the count()
*	function. To find out if the chain contains a particular pointer,
*	feed it to the has() function, that returns true if the item was found.
*	A similar function is itemIndex(), that returns the 0 based index of a
*	pointer or -1 if it was not found.
*
*
*	\section adding_it		Adding items
*	Items may be append() -ed, prepend() -ed to the chain or insert() -ed at a
*	given, 0 based, index. It should be noted that none of these functions
*	check if the item is already part of a chain. If the item is part of
*	another chain, the caller is required to extract the item before the call.
*
*	If the caller already inserted the items into the chain, ackAdd() function
*	may be used to inform the header AFTER the insertion. The function will
*	only update the counter and, if inserted item is first item, the pointer.
*
*
*	\section removing_it	Removing items
*	To extract an item from the chain WITHOUT deleting the item, remove()
*	function is used. The caller may provide either the 0 based index or the
*	pointer to the item to remove.
*
*	If the caller already removed the items from the chain, ackDel() function
*	may be used to inform the header AFTER the removal. The function will
*	only update the counter and, if the item is first item, the pointer. It is
*	expected that the item has it's internal fields intact (pointer to
*	next item is used to replace internal pointer).
*
*
*/
class	CC_HDL2D {

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

	friend class CC_L2D;
	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */


protected:

	/// pointer to first element in list
	class	CC_L2D*		Lip1;

	/// number of items that belong to this chain
	int					iCnt;

	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:


	/// constructor;
	CC_HDL2D()
	{ Lip1 = NULL; iCnt = 0; }


	/// destructor; will free resources;
	virtual				~CC_HDL2D();





	/// remove all items from this list by deleting them
	/**
 *	This function assumes that the CC_L2D
 *	elements were allocated using new() and it deletes them using delete).
 */
	void				erase		( void );


	/// set first item
	inline void			setFirst	(CC_L2D* pNew)
	{ Lip1 = pNew; }


	/// set number of items
	inline void			setCount	(int iNew)
	{ iCnt = iNew; }




	/// get first item
	inline CC_L2D*		first		( void )  const
	{ return Lip1; }


	/// get last item
	 CC_L2D*			last			( void )  const
	{ if (iCnt == 0) return NULL; return item(iCnt-1); }


	/// get nth item
	CC_L2D*				item			(int i) const;




	/// get the number of items
	inline int			count		( void ) const
	{ return iCnt; }


	/// returns the index of a particular item inside this chain
	/**
	*	The index is 0 based. If the pointer was not found inside the chain
	*	the function returns -1.
	*/
	int					itemIndex	( const CC_L2D* pIt)  const;


	/// tell if an item is part of this chain
	bool				has			( const CC_L2D* pIt)  const;




	/// append an item (insert after last)
	/**
	*	It should be noted that this function does not
	*	check if the item is already part of a chain. If the item is part of
	*	another chain, the caller is required to extract the item before the call.
	*/
	void				append		(CC_L2D* pIt);


	/// prepend an item (insert as first item)
	/**
	*	It should be noted that this function does not
	*	check if the item is already part of a chain. If the item is part of
	*	another chain, the caller is required to extract the item before the call.
	*/
	void				prepend		(CC_L2D* pIt);


	/// insert a item at specified index
	/**
	*	It should be noted that this function does not
	*	check if the item is already part of a chain. If the item is part of
	*	another chain, the caller is required to extract the item before the call.
	*/
	void				insert		(CC_L2D* p_new, int index);


	/// header is informed about an item being added
	/**
	*	If the caller already inserted the items into the chain, this function
	*	may be used to inform the header AFTER the insertion. The function will
	*	only update the counter and, if inserted item is first item, the pointer.
	*/
	void				ackAdd		(CC_L2D* pNew);




	/// remove the item at given index
	/**
	*	extract an item from the chain WITHOUT deleting the item
	*/
	void				remove		(int i);


	/// remove a particular item
	/**
	*	extract an item from the chain WITHOUT deleting the item
	*/
	void				remove		( CC_L2D* pIt);


	/// header is informed about an item being deleted
	/**
	*	If the caller already removed the items from the chain, ackDel() function
	*	may be used to inform the header AFTER the removal. The function will
	*	only update the counter and, if the item is first item, the pointer. It is
	*	expected that the item has it's internal fields intact (pointer to
	*	next item is used to replace internal pointer).
	*/
	void				ackDel		(CC_L2D* pNew);



	/// print the content of this object to debug output
	void				dbgDump		( void ) const;


	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class	CC_HDL2D	*/

/*  CLASS    =============================================================== */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/// class representing the list element in a linked list system
/**
*	\section overv	Overview
*	These lists are simple chains of objects. Each list must have:
*	- a header (CC_HDL2D) that holds a pointer to the first item
*	- a number of 0 or more items that inherit from CC_L2D (holding only a
*	forward and a backward pointer)
*
*	The items that inherit from this class are assumed to ne allocated using
*	new() c++ operator as they will be delete-d by some functions in CC_HDL2D.
*
*
*	\section new_del		Creation and destruction. Extracting from chain.
*
*	The constructor for this class either initialises the internal values
*	to a default, non-valid state or it appends this item to the chain indicated
*	by the header. As the item stores no dynamic content, the destructor does
*	nothing. Especially, as there is no pointer to the father stored, it does
*	NOT extract the item from the chain. To extract() an item from it's chain,
*	the caller needs to know the pointer to CC_HDL2D that hosts this item.
*
*	\section retrieve_info	Retrieveing data from it
*	The item only stores pointers to prev()-ious and to next() items. Both of
*	these functions return NULL if the item is first / last in the chain.
*	One may also find the index() of this item inside the chain that hosts it
*	presuming that it knows the pointer to CC_HDL2D.
*
*
*	\section ins_sup		Supporting siblings
*	Insertion of an item just before or after current one is very fast and
*	is supported by insBefore() and insAfter(). The caller must provide,
*	along with the pointer to the item to insert, a pointer to parent
*	CC_HDL2D instance.
*
*/
class	CC_L2D {

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

	friend class CC_HDL2D;

	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */
protected:

	/// pointer to next element in list
	class	CC_L2D*		LipN;

	/// pointer to previous element in list
	class	CC_L2D*		LipP;


	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:

	/// constructor; creates a simple, hanging element
	inline				CC_L2D()
	{ LipN = NULL; LipP = NULL; }

	/// constructor; appends this item to the chain managed by pFth
	inline				CC_L2D(CC_HDL2D* pFth)
	{ LipN = NULL; LipP = NULL; pFth->append(this); }

	/// destructor; will free resources;
	virtual				~CC_L2D(){}




	/// return next item
	inline CC_L2D*		next		( void ) const
	{ return LipN; }


	/// return previous item
	inline CC_L2D*		prev		( void ) const
	{ return LipP; }


	/// gets the index of a particular item inside the father
	int					index		( const CC_HDL2D* pFth) const;




	/// insert an item after this item
	void				insAfter	(CC_HDL2D* pFth, class CC_L2D* pNew);


	/// insert an item before this item
	void				insBefore	(CC_HDL2D* pFth, class CC_L2D* pNew);



	/// extract this item from the chain
	void				extract		(CC_HDL2D* pFth);



	/// print the content of this object to debug output
	void				dbgDump		( void ) const
	{ qDebug() << this << " prev: " << prev() << " next: " << next(); }

	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//
};	/*	class	CC_L2D	*/

/*  CLASS    =============================================================== */
//
//
//
//
#endif	//	__CC_L2D_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */


